package org.icop.frame.search;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.icop.model.MultiSet;
import org.icop.model.ValuedCorrespondence;
import org.icop.utils.StringUtils;
import org.jbpt.graph.abs.IEdge;
import org.jbpt.graph.abs.IGraph;
import org.jbpt.hypergraph.abs.IVertex;

import uk.ac.shef.wit.simmetrics.similaritymetrics.InterfaceStringMetric;
import uk.ac.shef.wit.simmetrics.similaritymetrics.Levenshtein;


/**
 * Checks for matches based on a given string metric 
 * over activity labels. All pairs of activities for which 
 * the labels have a metric value above the the threshold are 
 * selected. However, the match score is set to 1.0 independent 
 * of the actual computed distance value.
 * 
 * @author matthias.weidlich
 *
 */
public class StringMetricLabelSearcher<G extends IGraph<E,V>, E extends IEdge<V>, V extends IVertex> implements Searcher<G, E, V> {

	protected double cutoff;
	
	protected boolean wrapup;
	
	protected InterfaceStringMetric stringMetric;

	public StringMetricLabelSearcher(double cutoff){
		this(cutoff, false);
	}

	public StringMetricLabelSearcher(double cutoff, boolean wrapup){
		this(cutoff, wrapup, new Levenshtein());
	}
	
	public StringMetricLabelSearcher(double cutoff, boolean wrapup, InterfaceStringMetric stringMetric){
		this.cutoff = cutoff;
		this.wrapup = wrapup;
		this.stringMetric = stringMetric;
	}

	@Override
	public MultiSet<ValuedCorrespondence<V>> search(G sg1, G sg2, Collection<V> nodesInSg1, Collection<V> nodesInSg2, MultiSet<ValuedCorrespondence<V>> matches) {

		MultiSet<ValuedCorrespondence<V>> result = new MultiSet<>();

		if (this.wrapup) {
			Set<V> mappedVsFrom1 = new HashSet<>();
			Set<V> mappedVsFrom2 = new HashSet<>();
			for (ValuedCorrespondence<V> c: matches){
				mappedVsFrom1.addAll(c.getV1s());
				mappedVsFrom2.addAll(c.getV2s());
			}
			
			nodesInSg1.removeAll(mappedVsFrom1);
			nodesInSg2.removeAll(mappedVsFrom2);
		}
		
		for (V v1: nodesInSg1){
			String l1 = StringUtils.normalizeLabel(v1.getLabel());
			if (l1.equals("") )
				continue;
			for (V v2: nodesInSg2){
				String l2 = StringUtils.normalizeLabel(v2.getLabel());
				if (l2.equals("") )
					continue;
				
				double score = this.stringMetric.getSimilarity(l1, l2); 
				if (score >= cutoff){
					
//					System.out.println("match : " + l1 + " AND " + l2);
					Set<V> s1 = new HashSet<V>();
					s1.add(v1);
					Set<V> s2 = new HashSet<V>();
					s2.add(v2);
					result.add(new ValuedCorrespondence<V>(s1,s2,1.0));
				}
			}
		}
				
		return result;
	}

	
}